/**
 * Copyright(c) Live2D Inc. All rights reserved.
 *
 * Use of this source code is governed by the Live2D Open Software license
 * that can be found at https://www.live2d.com/eula/live2d-open-software-license-agreement_en.html.
 */

import {Live2DCubismFramework as cubismframework, LogLevel} from "../live2dcubismframework";
import {CSM_LOG_LEVEL, CSM_LOG_LEVEL_VERBOSE, CSM_LOG_LEVEL_DEBUG, CSM_LOG_LEVEL_INFO, CSM_LOG_LEVEL_WARNING, CSM_LOG_LEVEL_ERROR} from "../cubismframeworkconfig";


export const CubismLogPrint = (level: LogLevel, fmt: string, args: any[]) =>
{
    Live2DCubismFramework.CubismDebug.print(level, "[CSM]" + fmt, args);
}

export const CubismLogPrintIn = (level: LogLevel, fmt: string, args: any[]) =>
{
    CubismLogPrint(level, fmt + "\n", args);
}

export let CSM_ASSERT = (expr: any) =>
{
    console.assert(expr);
};


export let CubismLogVerbose = (fmt: string, ... args: any[]) => {};
export let CubismLogDebug = (fmt: string, ... args: any[]) => {};
export let CubismLogInfo = (fmt: string, ... args: any[]) => {};
export let CubismLogWarning = (fmt: string, ... args: any[]) => {};
export let CubismLogError = (fmt: string, ... args: any[]) => {};

if(CSM_LOG_LEVEL <= CSM_LOG_LEVEL_VERBOSE)
{
    CubismLogVerbose = (fmt: string, ... args: any[]) =>
    {
        CubismLogPrintIn(LogLevel.LogLevel_Verbose, "[V]" + fmt, args);
    };

    CubismLogDebug = (fmt: string, ... args: any[]) =>
    {
        CubismLogPrintIn(LogLevel.LogLevel_Debug, "[D]" + fmt, args);
    };

    CubismLogInfo = (fmt: string, ... args: any[]) =>
    {
        CubismLogPrintIn(LogLevel.LogLevel_Info, "[I]" + fmt, args);
    };

    CubismLogWarning = (fmt: string, ... args: any[]) =>
    {
        CubismLogPrintIn(LogLevel.LogLevel_Warning, "[W]" + fmt, args);
    };

    CubismLogError = (fmt: string, ... args: any[]) =>
    {
        CubismLogPrintIn(LogLevel.LogLevel_Error, "[E]" + fmt, args);
    };
}
else if(CSM_LOG_LEVEL == CSM_LOG_LEVEL_DEBUG)
{
    CubismLogDebug = (fmt: string, ... args: any[]) =>
    {
        CubismLogPrintIn(LogLevel.LogLevel_Debug, "[D]" + fmt, args);
    };

    CubismLogInfo = (fmt: string, ... args: any[]) =>
    {
        CubismLogPrintIn(LogLevel.LogLevel_Info, "[I]" + fmt, args);
    };

    CubismLogWarning = (fmt: string, ... args: any[]) =>
    {
        CubismLogPrintIn(LogLevel.LogLevel_Warning, "[W]" + fmt, args);
    };

    CubismLogError = (fmt: string, ... args: any[]) =>
    {
        CubismLogPrintIn(LogLevel.LogLevel_Error, "[E]" + fmt, args);
    };
}
else if(CSM_LOG_LEVEL == CSM_LOG_LEVEL_INFO)
{
    CubismLogInfo = (fmt: string, ... args: any[]) =>
    {
        CubismLogPrintIn(LogLevel.LogLevel_Info, "[I]" + fmt, args);
    };

    CubismLogWarning = (fmt: string, ... args: any[]) =>
    {
        CubismLogPrintIn(LogLevel.LogLevel_Warning, "[W]" + fmt, args);
    };

    CubismLogError = (fmt: string, ... args: any[]) =>
    {
        CubismLogPrintIn(LogLevel.LogLevel_Error, "[E]" + fmt, args);
    };
}
else if(CSM_LOG_LEVEL == CSM_LOG_LEVEL_WARNING)
{
    CubismLogWarning = (fmt: string, ... args: any[]) =>
    {
        CubismLogPrintIn(LogLevel.LogLevel_Warning, "[W]" + fmt, args);
    };

    CubismLogError = (fmt: string, ... args: any[]) =>
    {
        CubismLogPrintIn(LogLevel.LogLevel_Error, "[E]" + fmt, args);
    };
}
else if(CSM_LOG_LEVEL == CSM_LOG_LEVEL_ERROR)
{
    CubismLogError = (fmt: string, ... args: any[]) =>
    {
        CubismLogPrintIn(LogLevel.LogLevel_Error, "[E]" + fmt, args);
    };
}

//------------ LIVE2D NAMESPACE ------------
export namespace Live2DCubismFramework
{

    /**
     * デバッグ用のユーティリティクラス。
     * ログの出力、バイトのダンプなど
     */
    export class CubismDebug
    {
        /**
         * ログを出力する。第一引数にログレベルを設定する。
         * CubismFramework.initialize()時にオプションで設定されたログ出力レベルを下回る場合はログに出さない。
         *
         * @param logLevel ログレベルの設定
         * @param format 書式付き文字列
         * @param args 可変長引数
         */
        public static print(logLevel: LogLevel, format: string, args?: any[]): void
        {
            // オプションで設定されたログ出力レベルを下回る場合はログに出さない
            if(logLevel < cubismframework.CubismFramework.getLoggingLevel())
            {
                return;
            }

            const logPrint: Live2DCubismCore.csmLogFunction = cubismframework.CubismFramework.coreLogFunction;

            if (!logPrint)
                return;

            let buffer: string =
                format.replace(
                    /\{(\d+)\}/g,
                    (m, k) =>
                    {
                        return args[k];
                    }
                );
            logPrint(buffer);
        }

        /**
         * データから指定した長さだけダンプ出力する。
         * CubismFramework.initialize()時にオプションで設定されたログ出力レベルを下回る場合はログに出さない。
         *
         * @param logLevel ログレベルの設定
         * @param data ダンプするデータ
         * @param length ダンプする長さ
         */
        public static dumpBytes(logLevel: LogLevel, data: Uint8Array, length: number): void
        {
            for (let i: number = 0; i < length; i++)
            {
                if (i % 16 == 0 && i > 0) this.print(logLevel, "\n");
                else if (i % 8 == 0 && i > 0) this.print(logLevel, "  ");
                this.print(logLevel, "{0} ", [(data[i] & 0xFF)]);
            }

            this.print(logLevel, "\n");
        }

        /**
         * private コンストラクタ
         */
        private constructor()
        {

        }
    }
}

//------------ LIVE2D NAMESPACE ------------
